package com.zhuhjay.app.web.controller.system;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.zhuhjay.common.base.annotation.ApiLimiter;
import com.zhuhjay.common.base.model.vo.HttpResult;
import com.zhuhjay.common.web.annotation.Matching;
import com.zhuhjay.common.web.annotation.NotHttpResult;
import com.zhuhjay.common.web.annotation.RecordLog;
import com.zhuhjay.common.web.enums.MatchingMode;
import com.zhuhjay.framework.security.service.LoginService;
import com.zhuhjay.service.system.model.dto.UserLoginDto;
import com.zhuhjay.service.system.model.dto.UserRegisterDto;
import com.zhuhjay.service.system.model.entity.SystemUser;
import com.zhuhjay.service.system.model.vo.DirInfoVo;
import com.zhuhjay.service.system.model.vo.MdFileInfoVo;
import com.zhuhjay.service.system.service.SystemConfigService;
import com.zhuhjay.service.system.service.SystemDirService;
import com.zhuhjay.service.system.service.SystemFileService;
import com.zhuhjay.service.system.service.SystemUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.Collections;

/**
 * 公共接口，且不需要登录
 * @author ZhuHJay
 * @date 2023/2/25 22:50
 */
@Api(tags = "公共接口")
@Validated
@RestController
@Slf4j
public class CommonController {

    @Resource
    private SystemUserService userService;
    @Resource
    private SystemFileService fileService;
    @Resource
    private SystemDirService dirService;
    @Resource
    private LoginService loginService;
    @Resource
    private SystemConfigService configService;

    @RecordLog("用户登录")
    @ApiOperation("用户登录")
    @ApiLimiter(limit = 5, message = "登录频繁, 请稍后再试...")
    @PostMapping("login")
    public void login(@RequestBody UserLoginDto userLogin) {
        loginService.login(userLogin);
        // 记录用户登录时间
        userService.updateLastLoginTime(userLogin.getUsername());
    }

    @RecordLog("用户注册")
    @ApiOperation("用户注册")
    @ApiLimiter(limit = 2, expire = 60 * 60, message = "注册频繁, 请稍后再试...")
    @PostMapping("register")
    public void register(@RequestBody @Valid UserRegisterDto userRegister) {
        userService.register(userRegister);
    }

    @RecordLog("验证用户名(重置密码)")
    @ApiOperation("验证用户名(重置密码)")
    @GetMapping("common/reset/check/user/{username}")
    public HttpResult<?> username(@PathVariable @NotBlank(message = "账号不能为空") String username) {
        SystemUser user = userService.lambdaQuery().eq(SystemUser::getUsername, username).one();
        if (user == null) {
            return HttpResult.fail("该账号不存在, 请重新输入");
        }
        if (StrUtil.isBlank(user.getEmail())) {
            return HttpResult.fail("该账号未绑定邮箱, 无法重置密码, 请联系管理员");
        }
        // 发送邮件
        userService.send2ResetPwd(user);
        return HttpResult.ok(Collections.singletonMap("email", DesensitizedUtil.email(user.getEmail())));
    }

    @ApiOperation("重置密码")
    @PostMapping("common/reset/password/{email}/{code}")
    public HttpResult<?> resetPassword(
            @PathVariable @Matching(MatchingMode.Email) String email,
            @PathVariable @NotBlank(message = "请求失败") String code,
            @RequestBody @Matching(MatchingMode.Password) String password) {
        userService.resetPasswordByEmail(email, code, password);
        return HttpResult.ok("密码重置成功");
    }

    @ApiOperation("处理邮箱绑定")
    @GetMapping("common/bind/email/{email}/{code}")
    public HttpResult<?> bindEmail(
            @PathVariable @Matching(MatchingMode.Email) String email,
            @PathVariable @NotBlank(message = "请求错误") String code) {
        userService.bindEmail(email, code);
        return HttpResult.ok("邮箱绑定成功");
    }

    @ApiOperation("处理邮箱解绑")
    @GetMapping("common/unbind/email/{email}/{code}")
    public HttpResult<?> unbindEmail(
            @PathVariable @Matching(MatchingMode.Email) String email,
            @PathVariable @NotBlank(message = "请求错误") String code) {
        userService.unbindEmail(email, code);
        return HttpResult.ok("邮箱解绑成功");
    }

    @ApiOperation("获取文件预览地址")
    @GetMapping("common/config/previewUrl")
    public String previewUrl() {
        return configService.getConfigValue("system.fileview.url");
    }

    @ApiOperation("获取公众号二维码链接")
    @GetMapping("common/config/qrcodeUrl")
    public String qrcodeUrl() {
        return configService.getConfigValue("system.wxmp.qrcode");
    }

    @ApiOperation("获取公共文件夹信息")
    @GetMapping("common/dir/{id}")
    public DirInfoVo directory(@PathVariable @NotBlank(message = "文件夹id不能为空") String id) {
        return dirService.getPublic(id);
    }

    @ApiOperation("文件下载(FileSystem)")
    @GetMapping("common/download/{id}")
    @NotHttpResult
    public void download(
            @PathVariable @NotBlank(message = "文件下载失败") String id,
            HttpServletRequest request, HttpServletResponse response) {
        fileService.downloadFile(id, request, response);
    }

    @ApiOperation("文件预览(FileSystem)")
    @GetMapping("common/preview/{id}")
    @NotHttpResult
    public void preview(
            @PathVariable @NotBlank(message = "文件预览失败") String id,
            HttpServletRequest request, HttpServletResponse response) {
        fileService.previewFile(id, request, response);
    }

    @ApiOperation("文件预览(Markdown)")
    @GetMapping("common/md/preview/{id}")
    public MdFileInfoVo markdown(@PathVariable @NotBlank(message = "文件预览失败") String id) {
        return fileService.markdown(id);
    }

}
